--with Utilities;
with Io_Ports;
with Swindows;
use Swindows;
with Unsigned_Types;
use Unsigned_Types;  -- 1.8
with Raildefs, Dio192defs, Dda06defs, Int32defs, Halls2;
use Raildefs,Dda06defs;
with Controllers;
with Ada.Real_Time, Controllers;
use Ada.Real_Time, Controllers;


with Ada.Text_Io;--*
use Ada.Text_Io;--*
with Raildefs, IO_Ports,Unsigned_Types,Dda06defs, Dda06defs.Dio,Dac_Controller, Controllers;
use Raildefs,Unsigned_Types, Dda06defs, Dda06defs.Dio, Dac_Controller,Controllers;
with Ada.Text_Io; --*
with Swindows;
use Swindows;




package body Handheld_Controller is

   --Period : constant Time_Span := Milliseconds (100); -- Period to check controller is 100ms

   Cont_Address_1 : Unsigned_16 := Dda06defs.Base_Address + 12;
   Cont_Address_2 : Unsigned_16 := Dda06defs.Base_Address + 13;
   Cont_Address_3 : Unsigned_16 := Dda06defs.Base_Address + 14;


   --Masks
   Turn_Preference  : constant Unsigned_8 := 2#00011000#;
   Travel_Direction : constant Unsigned_8 := 2#00000100#;

   W_Int : Swindows.Window;
   procedure Init_W_Int (
         Win : in     Swindows.Window) is
   begin
      W_Int:= Win;
   end Init_W_Int;

   function Read_Dial (
         Hid : Controller_Id)
     return Dial_Value is
      Data    : Unsigned_8;
      CS_Data : CS_Register;
   begin
      CS_Data.Hid:=Natural(Hid)-1;--range is 0 to 2
      CS_Data.Eoc:=Off;
      IO_Ports.Write_IO_Port (CS, Unsigned(CS_Data));
      --Put_Line(W_int,"Io poRt hand held");
      IO_Ports.Write_IO_Port (AD_Hi,0);
      --Put_Line("Io poRt hand held");
      loop
         IO_Ports.Read_IO_Port (CS,Data);
         CS_Data:=CS_Register_Convert(Data);
         if CS_Data.Eoc= On then --finished conversion (1=buy 0=done)
            exit;
         end if;
      end loop;
      IO_Ports.Read_IO_Port (AD_Hi,Data);
      return Dial_Value(Data/4);--mask the 2 lsb
   end Read_Dial;





   task body Handheld_Controller_1_Thread is

      Prev_State : Unsigned_Types.Unsigned_8;
      Curr_State : Unsigned_Types.Unsigned_8;
      Temp1      : Unsigned_Types.Unsigned_8 := 0;
      Temp2      : Unsigned_Types.Unsigned_8 := 0;

      Next_Time : Time := Clock;

      Temp_State : Controller_State; --already initialised


   begin
      delay 1.0;
      loop

         delay until Next_Time;


         --Read Voltage Know and Set Cab Voltage
         Temp_State.Dial:=Read_Dial(1);
         if Temp_State.Dial < 32 then
            Dac_Controller.Set_Voltage(Cab_Type(1),0);
         else
            Dac_Controller.Set_Voltage(Cab_Type(1),Unsigned_8((Temp_State.Dial-32)*8));
         end if;


         -- get the current controller state
         Io_Ports.Read_Io_Port(
            Address => Cont_Address_1,
            Value   => Curr_State);


         Temp1:=Shift_Right(( Turn_Preference and Curr_State),3);
         Temp2:=Shift_Right((  Travel_Direction and Curr_State),2);


         if(Temp1=1) then
            Controllers.Start_Train_Direction_Right(1);
         end if;

         if(Temp1=2) then
            Controllers.Start_Train_Direction_Left(1);
         end if;

         if(Temp1=3) then
            Controllers.Start_Train_Direction_Centre(1);
         end if;


         if(Temp2=1) then
            Controllers.Start_Train_Forward (1);
         else
            Controllers.Start_Train_Backward (1);
         end if;

         Prev_State := Curr_State;

         Next_Time := Next_Time + Period;


      end loop;
   end Handheld_Controller_1_Thread;




   task body Handheld_Controller_2_Thread is
      Prev_State : Unsigned_Types.Unsigned_8;
      Curr_State : Unsigned_Types.Unsigned_8;
      Temp1      : Unsigned_Types.Unsigned_8 := 0;
      Temp2      : Unsigned_Types.Unsigned_8 := 0;

      Next_Time : Time := Clock;
      Temp_State : Controller_State; --already initialised

   begin
      delay 2.0;

      loop

         delay until Next_Time;



         --Read Voltage Know and Set Cab Voltage
         Temp_State.Dial:=Read_Dial(2);
         if Temp_State.Dial < 32 then
            Dac_Controller.Set_Voltage(Cab_Type(2),0);
         else
            Dac_Controller.Set_Voltage(Cab_Type(2),Unsigned_8((Temp_State.Dial-32)*8));
         end if;



         -- get the current controller state
         Io_Ports.Read_Io_Port(
            Address => Cont_Address_1,
            Value   => Curr_State);


         Temp1:=Shift_Right(( Turn_Preference and Curr_State),3);
         Temp2:=Shift_Right((  Travel_Direction and Curr_State),2);


         if(Temp1=1) then
            Controllers.Start_Train_Direction_Right(1);
         end if;

         if(Temp1=2) then
            Controllers.Start_Train_Direction_Left(1);
         end if;

         if(Temp1=3) then
            Controllers.Start_Train_Direction_Centre(1);
         end if;


         if(Temp2=1) then
            Controllers.Start_Train_Forward (1);
         else
            Controllers.Start_Train_Backward (1);
         end if;

         Prev_State := Curr_State;

         Next_Time := Next_Time + Period;


      end loop;


   end Handheld_Controller_2_Thread;


   task body Handheld_Controller_3_Thread is
      Prev_State : Unsigned_Types.Unsigned_8;
      Curr_State : Unsigned_Types.Unsigned_8;
      Temp1      : Unsigned_Types.Unsigned_8 := 0;
      Temp2      : Unsigned_Types.Unsigned_8 := 0;

      Next_Time  : Time             := Clock;
      Temp_State : Controller_State;          --already initialised


   begin
      delay 3.0;
      loop

         delay until Next_Time;

         --Read Voltage Know and Set Cab Voltage
         Temp_State.Dial:=Read_Dial(3);
         if Temp_State.Dial < 32 then
            Dac_Controller.Set_Voltage(Cab_Type(3),0);
         else
            Dac_Controller.Set_Voltage(Cab_Type(3),Unsigned_8((Temp_State.Dial-32)*8));
         end if;


         -- get the current controller state
         Io_Ports.Read_Io_Port(
            Address => Cont_Address_1,
            Value   => Curr_State);


         Temp1:=Shift_Right(( Turn_Preference and Curr_State),3);
         Temp2:=Shift_Right((  Travel_Direction and Curr_State),2);


         if(Temp1=1) then
            Controllers.Start_Train_Direction_Right(1);
         end if;

         if(Temp1=2) then
            Controllers.Start_Train_Direction_Left(1);
         end if;

         if(Temp1=3) then
            Controllers.Start_Train_Direction_Centre(1);
         end if;


         if(Temp2=1) then
            Controllers.Start_Train_Forward (1);
         else
            Controllers.Start_Train_Backward (1);
         end if;

         Prev_State := Curr_State;

         Next_Time := Next_Time + Period;


      end loop;

   end Handheld_Controller_3_Thread;

begin

   IO_Ports.Write_IO_Port (Pctl_Addr, Pctl_Init2);--set up tristate

end Handheld_Controller;
